package com.henrik.bak.esportcalendar.activity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import com.henrik.bak.esportcalendar.dbutils.EventsRepository;
import com.henrik.bak.esportcalendar.model.Calendar;
import com.henrik.bak.esportcalendar.model.Event;
import com.henrik.bak.esportcalendar.reader.IFeedReader;
import com.henrik.bak.esportcalendar.reader.TLCalendarReader;
import com.henrik.bak.esportcalendar.utils.CalendarAdapter;
import com.henrik.bak.esportcalendar.utils.CalendarUtils;

public class CalendarActivity extends Activity {

	private static final String TAG = "ESPORTS";

	public GregorianCalendar month, itemmonth;// calendar instances.
	IFeedReader reader;
	public CalendarAdapter adapter;// adapter instance
	public Handler handler;// for grabbing some event values for showing the dot
	// marker.
	public ArrayList<String> items; // container to store calendar items which
	// needs showing the event marker
	LinearLayout rLayout;
	CalendarUtils calUtils;
	Calendar tl_calendar = null;
	List<Event> userEvents = null;
	Map<String, Integer> map = new HashMap<String, Integer>();
	
	private String timezone;
	private Set<String> selectedGames;
	
	

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		loadCalendar();
		setContentView(R.layout.activity_calendar);
		Locale.setDefault(Locale.GERMAN);

		map.put("StarCraft 2", R.drawable.sc2_icon);
		map.put("League of Legends", R.drawable.lol_icon);
		map.put("Dota 2", R.drawable.dota_2_icon);
		map.put("Brood War", R.drawable.bw_icon);
		map.put("Other", R.drawable.other_icon);

		rLayout = (LinearLayout) findViewById(R.id.text);
		month = (GregorianCalendar) GregorianCalendar.getInstance();
		itemmonth = (GregorianCalendar) month.clone();

		items = new ArrayList<String>();
		calUtils = new CalendarUtils();
		calUtils.setCalendar(tl_calendar);
		Log.d("ESPORTS", "User events: "+userEvents.toString());
		CalendarUtils.getUserEvents().addAll(userEvents);

		adapter = new CalendarAdapter(this, month);

		final GridView gridview = (GridView) findViewById(R.id.calendar_gridview);
		gridview.setAdapter(adapter);
		
		loadPref();

		handler = new Handler();
		handler.post(calendarUpdater);

		TextView title = (TextView) findViewById(R.id.title);
		title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));

		RelativeLayout header = (RelativeLayout) findViewById(R.id.header);

		header.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (gridview.getVisibility() == View.VISIBLE)
					gridview.setVisibility(View.GONE);
				else
					gridview.setVisibility(View.VISIBLE);
			}
		});

		RelativeLayout previous = (RelativeLayout) findViewById(R.id.previous);

		previous.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				setPreviousMonth();
				refreshCalendar();
			}
		});

		RelativeLayout next = (RelativeLayout) findViewById(R.id.next);
		next.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				setNextMonth();
				refreshCalendar();

			}
		});

		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView parent, View v, int position,
					long id) {
				// removing the previous view if added
				if (((LinearLayout) rLayout).getChildCount() > 0) {
					((LinearLayout) rLayout).removeAllViews();
				}
				((CalendarAdapter) parent.getAdapter()).setSelected(v);
				String selectedGridDate = CalendarAdapter.dayString
						.get(position);
				String[] separatedTime = selectedGridDate.split("-");
				String gridvalueString = separatedTime[2].replaceFirst("^0*",
						"");// taking last part of date. ie; 2 from 2012-12-02.
				int gridvalue = Integer.parseInt(gridvalueString);
				// navigate to next or previous month on clicking offdays.
				if ((gridvalue > 10) && (position < 8)) {
					setPreviousMonth();
					refreshCalendar();
				} else if ((gridvalue < 7) && (position > 28)) {
					setNextMonth();
					refreshCalendar();
				}
				((CalendarAdapter) parent.getAdapter()).setSelected(v);
				ScrollView scroll = new ScrollView(getApplicationContext());

				LayoutInflater inflater = LayoutInflater
						.from(getApplicationContext());

				scroll.setBackgroundColor(getResources().getColor(
						android.R.color.transparent));
				scroll.setLayoutParams(new LayoutParams(
						LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

				LinearLayout scrollBaseLayout = new LinearLayout(
						getApplicationContext());
				scrollBaseLayout.setOrientation(LinearLayout.VERTICAL);

				scroll.addView(scrollBaseLayout);
				for (int i = 0; i < calUtils.getStartDates().size(); i++) {
					if (calUtils.getStartDates().get(i)
							.equals(selectedGridDate)) {

						RelativeLayout customRow = (RelativeLayout) inflater
								.inflate(R.layout.event_view, null, false);

						ImageView icon = (ImageView) customRow
								.findViewById(R.id.icon);
						TextView title = (TextView) customRow
								.findViewById(R.id.title);
						TextView desc = (TextView) customRow
								.findViewById(R.id.desc);
						TextView time = (TextView) customRow
								.findViewById(R.id.time);

						final Event event = calUtils.getEvents().get(i);

						try {
							icon.setImageResource(map.get(event.getType()));
						} catch (NullPointerException ex) {
							icon.setImageResource(map.get("Other"));
						}

						title.setText(event.getTitle());
						if (event.getDescription() != null) {
							String noHTMLString = replaceLinks(
									event.getDescription()
											.replaceAll("\\<.*?>", "")
											.replaceAll("\\[.*?]", "")
											.replaceAll(".png", ".png "))
									.trim().replaceAll(" +", " ");

							Integer length = noHTMLString.length();
							if (length > 75) {
								desc.setText(noHTMLString.substring(0, 75)
										+ "...");
							} else {
								desc.setText(noHTMLString);
							}
						}
						String minute = (event.getEventDate().getMinuteOfHour() < 10) ? "0"
								+ event.getEventDate().getMinuteOfHour()
								: "" + event.getEventDate().getMinuteOfHour();
						String hour = (event.getEventDate().getHourOfDay() < 9) ? "0"
								+ event.getEventDate().getHourOfDay()
								: "" + event.getEventDate().getHourOfDay();

						time.setText(hour + ":" + minute);

						// add the textview to the linearlayout
						scrollBaseLayout.addView(customRow);

					}
				}
				rLayout.addView(scroll);
			}

		});
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		loadPref();
		refreshCalendar();
	}

	private void loadPref() {
		SharedPreferences mySharedPreferences = PreferenceManager
				.getDefaultSharedPreferences(this);

		timezone = mySharedPreferences.getString("prefTimezone", null);

		selectedGames = mySharedPreferences.getStringSet(
				"prefGames", null);
		Log.d(TAG, timezone);
		Log.d(TAG, selectedGames.toString());
	}

	private void loadCalendar() {
		reader = new TLCalendarReader();
		String xml = null;
		try {
			xml = new getTLFeed().execute().get();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} catch (ExecutionException e1) {
			e1.printStackTrace();
		}

		Serializer ser = new Persister();
		try {
			tl_calendar = ser.read(Calendar.class, xml);
			EventsRepository repos = new EventsRepository(this);
			userEvents = (List<Event>)repos.getAll();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private String replaceLinks(String text) {

		String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(text);
		while (m.find()) {
			String urlStr = m.group();
			if (urlStr.startsWith("(") && urlStr.endsWith(")")) {
				urlStr = urlStr.substring(1, urlStr.length() - 1);
			}
			if (urlStr.endsWith("png") || urlStr.endsWith("jpg"))
				text = text.replace(urlStr, "");
		}
		return text;
	}

	protected void setNextMonth() {
		if (month.get(GregorianCalendar.MONTH) == month
				.getActualMaximum(GregorianCalendar.MONTH)) {
			month.set((month.get(GregorianCalendar.YEAR) + 1),
					month.getActualMinimum(GregorianCalendar.MONTH), 1);
		} else {
			month.set(GregorianCalendar.MONTH,
					month.get(GregorianCalendar.MONTH) + 1);
		}

	}

	protected void setPreviousMonth() {
		if (month.get(GregorianCalendar.MONTH) == month
				.getActualMinimum(GregorianCalendar.MONTH)) {
			month.set((month.get(GregorianCalendar.YEAR) - 1),
					month.getActualMaximum(GregorianCalendar.MONTH), 1);
		} else {
			month.set(GregorianCalendar.MONTH,
					month.get(GregorianCalendar.MONTH) - 1);
		}
	}

	public void refreshCalendar() {
		TextView title = (TextView) findViewById(R.id.title);

		adapter.refreshDays();
		adapter.notifyDataSetChanged();
		handler.post(calendarUpdater); // generate some calendar items

		title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu items for use in the action bar
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.calendar, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle presses on the action bar items
		switch (item.getItemId()) {
		case R.id.action_search:
			openSearch();
			return true;
		case R.id.action_settings:
			openSettings();
			return true;
		case R.id.action_add:
			addEvent();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void addEvent() {
		Intent i = new Intent(CalendarActivity.this, AddEventActivity.class);
		startActivity(i);	
	}

	private void openSettings() {
		Intent intent = new Intent(CalendarActivity.this, PreferencesActivity.class);
		startActivityForResult(intent, 0);
	}

	private void openSearch() {
		Log.d(TAG, "search");

	}

	public Runnable calendarUpdater = new Runnable() {

		@Override
		public void run() {
			items.clear();
			
			if (timezone.isEmpty())
				timezone = "Europe/Budapest";
			if (selectedGames == null || selectedGames.isEmpty()) {
				selectedGames = new HashSet<String>();
				selectedGames.addAll(Arrays.asList(getResources().getStringArray(R.array.games)));	
			}

			// Print dates of the current week
			calUtils.readCalendarEvent(CalendarActivity.this, timezone, selectedGames);

			for (int i = 0; i < calUtils.getStartDates().size(); i++) {
				itemmonth.add(GregorianCalendar.DATE, 1);
				items.add(calUtils.getStartDates().get(i).toString());
			}
			Log.d("ESPORTS", items.toString());
			adapter.setItems(items);
			adapter.notifyDataSetChanged();
		}
	};

	class getTLFeed extends AsyncTask<Void, Void, String> {

		@Override
		protected String doInBackground(Void... voids) {
			return reader.read();
		}

		@Override
		protected void onPostExecute(String result) {
		}

	}
}
